#include "MS51_16K.H"

#define SYSCLK 24000000
#define BOARDNAME "EEPROM32"
#define BOARDNAME_LENGTH 8


//595控制
//控制位 SS = P15
//CLK     P10
//MOSI   P00

#define OE P05
#define CE P30
#define WE P17


//支持芯片
#define CHIP_SIZE 6
//缓存
#define BUFF_LEN 128

//常量定义支持的片
code uint32_t chips[CHIP_SIZE] = {
  39010,39020,39040,
	39011,39021,39041
};

char cmd;

bdata uint8_t bData;     // Bit-addressable var
sbit bData0 = bData ^ 0; // bit 0 of bData
sbit bData1 = bData ^ 1;
sbit bData2 = bData ^ 2;
sbit bData3 = bData ^ 3;
sbit bData4 = bData ^ 4;
sbit bData5 = bData ^ 5;
sbit bData6 = bData ^ 6;
sbit bData7 = bData ^ 7; // bit 7 of bData

// page buffer
xdata char pageBuffer[BUFF_LEN];
xdata char cmdBuffer[22];
xdata uint32_t chipId=0,startAddr=0,endAddr=0,dataLength=0;
xdata uint8_t startPage=0,endPage=0;


char putchar(char c)
{
  //DISABLE_UART0_INTERRUPT;
  TI = 0;
  SBUF = c;
  while(!TI);
  TI = 0;
  //ENABLE_UART0_INTERRUPT;
  return c;
}
void lock28();
void unlock28();

void init(void)
{
    MODIFY_HIRC(HIRC_24);
    ALL_GPIO_QUASI_MODE;
	
    //Enable_UART0_VCOM_printf_24M_115200();
		// 替换波特率
    P06_QUASI_MODE;
    UART_Open(24000000,UART0_Timer1,115200);
    //UART_Open(24000000,UART0_Timer1,250000);
    ENABLE_UART0_PRINTF;
	
    TI = 0;
    
    ENABLE_UART0_INTERRUPT;                                  /* Enable UART0 interrupt */
    ENABLE_GLOBAL_INTERRUPT;                                  /* Global interrupt enable */
  
    //OE CE WE
    P05_PUSHPULL_MODE;
    P30_PUSHPULL_MODE;
    P17_PUSHPULL_MODE;
    //默认we高
    WE=1;
}

void SPI_Initial(void)
{      
    P15_PUSHPULL_MODE;                                  // P15 (SS) Quasi mode
    P10_PUSHPULL_MODE;                                  // P10 (SPCLK) Quasi mode
    P00_PUSHPULL_MODE;                                  // P00 (MOSI) Quasi mode
    P01_QUASI_MODE;                                     // P01 (MISO) Quasi mode
    
    clr_SPCR_SPR1;
    set_SPCR_SPR0;
    /* /SS General purpose I/O ( No Mode Fault ) */
    set_SPSR_DISMODF;
    clr_SPCR_SSOE;

    /* SPI in Master mode */
    set_SPCR_MSTR;

    /* MSB first */
    clr_SPCR_LSBFE;

    clr_SPCR_CPOL;
    clr_SPCR_CPHA;
    
    /* Enable SPI function */
    set_SPCR_SPIEN;
  
    //设置P15初始0
    SS = 0;
}


//  INPUT: NUM (1 - 255)
//       MOV  R7, #NUM  (2 CYCLE)
//       LCALL delay_ns (4 CYCLE)
//LABLE: DJNZ R7, LABLE (4 CYCLE)
//       RET            (5 CYCLE)
//                      总共需要 (2 + 4 + 4 * N + 5) CYCLE 
//                               (11 + 4*N) / 24 us = (0.625us ~ 42.958us)
void delay_ns(uint8_t ds){
  while(--ds)
  {}
}


/*******************************************************************************
**void Uart_SendString(u8 *data , u8 strlen)
**send Strings
**in:u8 *data   ,  u8 strlen
**return:null
**send:datasheet, Uart_SendString("datasheet" ,9);
*******************************************************************************/
void Uart_SendString(uint8_t *datas,uint8_t strlen)
{
	unsigned char datalen;
  for(datalen = 0 ; datalen < strlen ; datalen++)
  {
    putchar(datas[datalen]);
  }
}

//执行命令缓存
void readCommand(void)
{
  char c;
  uint8_t i=0;
  uint8_t idx=0;
  for(i=0; i< 22; i++) cmdBuffer[i] = 0;
  do
  {
    if (uart0_receive_flag)
    {
      c=uart0_receive_data;
      cmdBuffer[idx++]=c;
      uart0_receive_flag = 0;
    }
  }
  while(c != '\n' && c != '\r' && idx < 21);
  cmdBuffer[idx-1]=0;
}

//读取写入数据缓存
void readBuffer(void)
{
  uint8_t i=0;
  uint8_t idx=0;
	
	ENABLE_UART0_INTERRUPT;
  delay_ns(100);
  for(i=0; i< BUFF_LEN; i++) pageBuffer[i] = 0;
  do
  {
    if (uart0_receive_flag)
    {
      pageBuffer[idx++]=uart0_receive_data;
      uart0_receive_flag = 0;
    }
  }
  while(idx < BUFF_LEN);
	DISABLE_UART0_INTERRUPT;
}

uint8_t hexDigit(char c) {
  if      (c >= '0' && c <= '9') 
    return c - '0';
  else if (c >= 'a' && c <= 'f') 
    return c - 'a' + 10;
  else if (c >= 'A' && c <= 'F') 
    return c - 'A' + 10;
  else 
    return 0;
}

uint8_t hexByte(char *a) {
  return ((hexDigit(a[0])*16) + hexDigit(a[1]));
}


uint32_t hexChip(char *dat){
  char* p = dat;
  uint32_t re = 0;
  if(dat[1]>=0x30 && dat[1]<=0x39)
    re+=(dat[1]-0x30)*10000;
  if(dat[2]>=0x30 && dat[2]<=0x39)
    re+=(dat[2]-0x30)*1000;
  if(dat[3]>=0x30 && dat[3]<=0x39)
    re+=(dat[3]-0x30)*100;
  if(dat[4]>=0x30 && dat[4]<=0x39)
    re+=(dat[4]-0x30)*10;
  if(dat[5]>=0x30 && dat[5]<=0x39)
    re+=(dat[5]-0x30)*1;
  return re;
}

uint32_t hexWord(char *dat) {
  return (
    (hexDigit(dat[0])*4096)+
    (hexDigit(dat[1])*256)+
    (hexDigit(dat[2])*16)+
    (hexDigit(dat[3])));
}

void read_mode(void){
  P16_INPUT_MODE;
  P14_INPUT_MODE;
  P13_INPUT_MODE;
  P12_INPUT_MODE;
  P11_INPUT_MODE;
  P02_INPUT_MODE;
  P03_INPUT_MODE;
  P04_INPUT_MODE;
	
//  P16_QUASI_MODE;
//  P14_QUASI_MODE;
//  P13_QUASI_MODE;
//  P12_QUASI_MODE;
//  P11_QUASI_MODE;
//  P02_QUASI_MODE;
//  P03_QUASI_MODE;
//  P04_QUASI_MODE;
}

void write_mode(void){
  P16_PUSHPULL_MODE;
  P14_PUSHPULL_MODE;
  P13_PUSHPULL_MODE;
  P12_PUSHPULL_MODE;
  P11_PUSHPULL_MODE;
  P02_PUSHPULL_MODE;
  P03_PUSHPULL_MODE;
  P04_PUSHPULL_MODE;
}

//读数据
uint8_t read_data_bus(){
    bData0 = P16;
    bData1 = P14;
    bData2 = P13;
    bData3 = P12;
    bData4 = P11;
    bData5 = P02;
    bData6 = P03;
    bData7 = P04;
    
    return bData;
}

//写数据
void write_data_bus(char dat){
  P16=dat&1;
  P14=dat>>1&1;
  P13=dat>>2&1;
  P12=dat>>3&1;
  P11=dat>>4&1;
  P02=dat>>5&1;
  P03=dat>>6&1;
  P04=dat>>7&1;
}


//是否支持
uint8_t chipSupport(uint32_t chipId){
  int i;
  for(i=0;i<CHIP_SIZE;i++){
    if(chips[i]==chipId)
      return 1;
  }
  return 0;
}

//检查是否支持并返回结果
void check(uint32_t chipId){
  if(chipSupport(chipId)){
    Uart_SendString("ok\r\n",4);
  }else{
    Uart_SendString("Unsupport\r\n",11);
  }
}


//设置地址
void setAddress(uint32_t addr,uint32_t chipId) {
	
	// 27 28 TODO 默认用 29
	if(chipId==2864 || chipId==28256){
	
	}
	
	//if(chipId==29010||chipId==29020||chipId==29040||chipId==29011||chipId==29021||chipId==29041){
		
	//}
	
	
  //SPI输出高位，然后输出低位
  Spi_Write_Byte((addr>>16)&0x07);//只用了3条线
  Spi_Write_Byte((addr>>8)&0xff);
  Spi_Write_Byte(addr&0xff);

  //控制595上升沿输出锁存数据
  SS=1;
  SS=0;
}

// 根据地址读取数据
char readByte(uint32_t addr,uint32_t chipId){
  char b = 0;
  setAddress (addr,chipId);
  
  //延时
  if(chipId==2864||chipId==28256){
		delay_ns(3);
	}else{
		delay_ns(2);
	}
  
  b = read_data_bus();
  return b;
}

// 读取芯片内容(读取的时候ce oe全部拉低，改变地址就可以输出)
void readBinary(uint32_t addr, uint32_t count,uint32_t chipId) {
  //28读取需要高位
  if(chipId==2864||chipId==28256){
    WE=1;
  }
	if(chipId==29010||chipId==29020||chipId==29040||chipId==29011||chipId==29021||chipId==29041){
		WE=1;
	}
	delay_ns(1);
  OE=0;
  CE=0;
  while (count) {
		putchar(readByte(addr++, chipId));
    count--;
  }
  OE=1;
  CE=1;
}


void check_buff(uint32_t addr, uint32_t chipId){
  int i=0;
  read_mode();
  if(chipId==2864||chipId==28256){
    WE=1;
    delay_ns(255);
  }
  //读数据校验
  CE=0;
  delay_ns(10);
  for(i=0;i<BUFF_LEN ;i++){
    uint8_t rd = readByte(addr+i,chipId);
    if(pageBuffer[i]!=rd){
      printf("0x");
      printf("%hhx",addr+i);
      printf("=");
      printf("%hhx",rd);
      printf(",");
      printf("%hhx",pageBuffer[i]);
      printf(" ");
      break;
    }
  }
  CE=1;
	Uart_SendString("ok\r\n",4);
}


void write_byte28(uint32_t address, char dat,uint32_t chipId) {
  write_data_bus(dat);
  setAddress(address,chipId);
  delay_ns(3);
  WE=0;
  delay_ns(5);
  WE=1;
}

void write28(uint32_t addr,uint32_t chipId){
  int i=0;
  readBuffer();
  
  WE=1;
	
  write_mode();
  OE=1;
  CE=0;
  delay_ns(10);

  for(i=0;i<BUFF_LEN;i++){
    write_byte28(addr+i,pageBuffer[i],chipId);
  }

  CE=1;
  read_mode();
  //WE读取
  WE=1;
  
  delay_ns(255);

  check_buff(addr,chipId);

  setAddress(0,chipId);
  
  delay_ns(255);
  
}

void write_byte29(uint32_t address, char dat,uint32_t chipId) {
  write_data_bus(dat);
  setAddress(address,chipId);
  delay_ns(3);
  WE=0;
  delay_ns(5);
  WE=1;
}

void write29(uint32_t addr,uint32_t chipId){
	
  int i=0;
  readBuffer();
  
  WE=1;
	
  write_mode();
  OE=1;
  CE=0;
  delay_ns(10);

	
	
  // A29 MX29 SSF39
  if (chipId==29010||chipId==29020||chipId==29040) {
    CE = 0;

    if(addr==0){
      for (i = 0; i < BUFF_LEN; i++) {
        write_byte29 (0x5555, 0xaa, chipId);
        write_byte29 (0x2aaa, 0x55, chipId);
        write_byte29 (0x5555, 0xa0, chipId);
        write_byte29 (addr+i, pageBuffer[i], chipId);
      }
    }
    
    for (i = 0; i < BUFF_LEN; i++) {
      write_byte29 (0x5555, 0xaa, chipId);
      write_byte29 (0x2aaa, 0x55, chipId);
      write_byte29 (0x5555, 0xa0, chipId);
      write_byte29 (addr+i, pageBuffer[i], chipId);
    }
    // Winbond 29 特殊的 128 字节写入
  } else if (chipId==29011||chipId==29021||chipId==29041) {
    CE = 0;
    write_byte29 (0x5555, 0xaa, chipId);
    write_byte29 (0x2aaa, 0x55, chipId);
    write_byte29 (0x5555, 0xa0, chipId);
    for (i = 0; i < BUFF_LEN; i++) {
      write_byte29(addr+i, pageBuffer[i], chipId);
    }
  // 其他芯片报错
  } else {
		Uart_SendString("Not support chip for write\r\n",28);
    return;
  }
  
  //delay_ns(255);
  //check_buff(addr,chipId);
  //setAddress(0,chipId);
  // 不校验数据，直接返回ok
	Uart_SendString("ok\r\n",4);
  //delay_ns(10);
}	

void eraser28(uint32_t chipId){
	uint32_t i;
	uint32_t count;
	
  Uart_SendString("ok\r\n",4);
	
	unlock28();
	
  delay_ns(255);
	
	write_mode();
	WE=1;
  OE=1;
  CE=0;
  delay_ns(10);
	
	count = chipId==28256?32768:8192;
	
  for(i=0;i<count;i++){
    write_byte28(i,0xff,chipId);
  }
	
  CE=1;
	
}

void eraser29(uint32_t chipId) {
  OE = 1;
  CE = 0;
  write_mode();                            // set data bus pins as output
  //reset
  write_byte29 (0x0000, 0xf0, chipId);
	
	
  Uart_SendString("ok\r\n",4);
	
  delay_ns(255);
  
	write_byte29 (0x5555, 0xaa, chipId);             // write code sequence
  write_byte29 (0x2aaa, 0x55, chipId);
  write_byte29 (0x5555, 0x80, chipId);
  write_byte29 (0x5555, 0xaa, chipId);
  write_byte29 (0x2aaa, 0x55, chipId);
  write_byte29 (0x5555, 0x10, chipId);
	
  delay_ns(255);
	
  CE = 1;
	
  read_mode();
  delay_ns(255);
	
}


void lock28(){
  WE=1;
  OE=1;
  CE=0;
  write_mode();
  write_byte28 (0x5555, 0xaa, 28256);
  write_byte28 (0x2aaa, 0x55, 28256);
  write_byte28 (0x5555, 0xa0, 28256);
  CE=1;
  read_mode();
  delay_ns(255);
}

void unlock28(){
  WE=1;
  OE=1;
  CE=0;
  write_mode();
  write_byte28 (0x5555, 0xaa, 28256);
  write_byte28 (0x2aaa, 0x55, 28256);
  write_byte28 (0x5555, 0x80, 28256);
  write_byte28 (0x5555, 0xaa, 28256);
  write_byte28 (0x2aaa, 0x55, 28256);
  write_byte28 (0x5555, 0x20, 28256);
  CE=1;
  WE=1;
  read_mode();
  delay_ns(255);
}


/**
接收字符串类型: v  28256 00000 7ffff
**/

void main (void) 
{
    init();
    SPI_Initial();
    read_mode();
	    
    while(1)
    {
      //打开中断
      ENABLE_UART0_INTERRUPT;
			
      readCommand();

      //读取命令后关闭中断
      DISABLE_UART0_INTERRUPT;

      cmd = cmdBuffer[0];                  //指令
      chipId    = hexChip(cmdBuffer+2);    //芯片
      startPage = hexDigit(cmdBuffer[9]);
      startAddr = hexWord(cmdBuffer+10);   //开始地址
      endPage   = hexDigit(cmdBuffer[15]);
      endAddr   = hexWord(cmdBuffer+16);   //结束地址
			
			startAddr &= 0xffff;
			endAddr &= 0xffff;
			startPage &= 0xf;
			endPage   &= 0xf;
			endPage = endPage < startPage ? startPage : endPage;
      
			
			startAddr = (startPage * 65536) + startAddr;
			endAddr   = (endPage * 65536) + endAddr;
			
			endAddr = endAddr < startAddr ? startAddr : endAddr;
			
      // 数据长度
      dataLength = endAddr - startAddr + 1;
      
			
      switch(cmd){
        
        case 'i':
            Uart_SendString(BOARDNAME,BOARDNAME_LENGTH);
            Uart_SendString("\r\n",2);
            break;
        
        case 'v':
            Uart_SendString("1.0\r\n",5);
            break;
        
        case 't':
            Uart_SendString("Ready\r\n",7);
            break;
        
        case 'l':
            lock28();
            break;
        
        case 'u':
            unlock28();
            break;
        
        case 'c':   
            check(chipId);
            break;
        
        case 'r':   
            readBinary(startAddr, dataLength,chipId);
            break;
        
        
        case 'w':
            if(chipId==2764||chipId==27128||chipId==27256||chipId==27512){
              //write27(startAddr,dataLength,chipId);
              break;
            }else if(chipId==2864||chipId==28256){
              write28(startAddr,chipId);//长度使用buff
              break;
            }else if(chipId==29010||chipId==29020||chipId==29040||chipId==29011||chipId==29021||chipId==29041){
							write29(startAddr,chipId);
              break;
            }else{
              //printf("Write unsupport");
              Uart_SendString("Write unsupport\r\n",17);
              break;
            }
				
				// 擦除
        case 'e':
						if(chipId==2864||chipId==28256){
              eraser28(chipId);
            }else if(chipId==29010||chipId==29020||chipId==29040||chipId==29011||chipId==29021||chipId==29041){
							eraser29(chipId);            
						}
            break;
						
						
						
				// 测试代码
        case 'a':
            setAddress(startAddr, chipId);
            break;
        case 'b':
            write_mode();
            write_data_bus(0xff);
            break;
        case 'd':
            write_mode();
            write_data_bus(0x00);
            break;
				
        default:    break;
        
      }
    }    
}
